import FileUploader from '@/components/FileUploader';
import PictureUploader from '@/components/PictureUploader';
import { OSS_HOST } from '@/constants';
import FileConfigForm from '@/pages/Generator/Add/components/FileConfigForm';
import GeneratorMaker from '@/pages/Generator/Add/components/GeneratorMaker';
import ModelConfigForm from '@/pages/Generator/Add/components/ModelConfigForm';
import {
  addGeneratorUsingPost,
  getGeneratorVoByIdUsingGet,
  updateGeneratorUsingPost,
} from '@/services/backend/generatorController';
import { useSearchParams } from '@@/exports';
import { CloudUploadOutlined, InfoCircleOutlined } from '@ant-design/icons';
import type { ProFormInstance } from '@ant-design/pro-components';
import {
  ProCard,
  ProFormSelect,
  ProFormText,
  ProFormTextArea,
  StepsForm,
} from '@ant-design/pro-components';
import { ProFormItem } from '@ant-design/pro-form';
import { history } from '@umijs/max';
import { Button, message, Modal, Upload, UploadFile, UploadProps } from 'antd';
import { RcFile } from 'antd/es/upload';
import React, { useEffect, useRef, useState } from 'react';

const GeneratorAddPage: React.FC = () => {
  const formRef = useRef<ProFormInstance>();
  const [searchParams] = useSearchParams();
  const id = searchParams.get('id');
  // 旧数据对象
  const [oldData, setOldData] = useState<API.GeneratorEditRequest>();
  // 第一表单数据：元数据基础信息
  const [basicInfo, setBasicInfo] = useState<API.GeneratorEditRequest>();
  // 第二表单数据，元数据文件配置信息
  const [modelConfig, setModelConfig] = useState<API.ModelConfig>();
  // 第三表单数据，元数据模型配置信息
  const [fileConfig, setFileConfig] = useState<API.FileConfig>();
  const [importModalVisible, setImportModalVisible] = useState(false);
  const [importFileList, setImportFileList] = useState<UploadFile[]>([]);
  const [formKey, setFormKey] = useState(Date.now()); // 用于强制重新渲染表单

  /**
   * 更新操作前，加载旧数据
   */
  const loadData = async () => {
    if (!id) {
      return;
    }

    try {
      // @ts-ignore
      const res = await getGeneratorVoByIdUsingGet({ id });

      // 处理文件路径
      if (res.data) {
        const { distPath } = res.data ?? {};
        if (distPath) {
          // @ts-ignore
          res.data.distPath = [
            {
              uid: id,
              name: '文件' + id,
              status: 'done',
              url: OSS_HOST + distPath,
              response: distPath,
            } as UploadFile,
          ];
        }
        setOldData(res.data);
      }
    } catch (error: any) {
      message.error('加载数据失败' + error.message);
    }
  };

  useEffect(() => {
    if (id) {
      loadData();
    }
  }, [id]);

  /**
   * 创建
   *
   * @param values
   */
  const doAdd = async (values: API.GeneratorAddRequest) => {
    try {
      const res = await addGeneratorUsingPost(values);
      if (res.data) {
        message.success('创建成功');
        history.push(`/generator/detail/${res.data}`);
      }
    } catch (e: any) {
      message.error('创建失败' + e.message);
    }
  };

  /**
   * 更新
   *
   * @param values
   */
  const doUpdate = async (values: API.GeneratorEditRequest) => {
    try {
      const res = await updateGeneratorUsingPost(values);
      if (res.data) {
        message.success('更新成功');
        history.push(`/generator/detail/${id}`);
      }
    } catch (e: any) {
      message.error('更新失败' + e.message);
    }
  };

  /**
   * 提交
   *
   * @param values
   */
  const doSubmit = async (values: API.GeneratorAddRequest) => {
    // 数据转换
    if (!values.fileConfig) {
      values.fileConfig = {};
    }
    if (!values.modelConfig) {
      values.modelConfig = {};
    }

    // 文件列表转url
    if (values.distPath && values.distPath.length > 0) {
      // @ts-ignore
      values.distPath = values.distPath[0].response;
    }

    if (id) {
      await doUpdate({
        ...values,
        // @ts-ignore
        id,
      });
    } else {
      await doAdd(values);
    }
  };

  const beforeImportUpload = (file: RcFile) => {
    const isJson = file.type === 'application/json' || file.name.endsWith('.json');
    if (!isJson) {
      message.error('只能上传 JSON 文件!');
    }
    return isJson;
  };

  const handleImportChange: UploadProps['onChange'] = (info) => {
    let newFileList = [...info.fileList];

    // 限制只能上传一个文件
    newFileList = newFileList.slice(-1);

    // 读取文件内容
    newFileList = newFileList.map((file) => {
      if (file.response) {
        file.url = file.response.url;
      }
      return file;
    });

    setImportFileList(newFileList);
  };

  const handleImport = () => {
    if (importFileList.length === 0) {
      message.warning('请先上传 JSON 文件');
      return;
    }

    const file = importFileList[0];
    const reader = new FileReader();

    reader.onload = (e) => {
      try {
        const content = e.target?.result as string;
        const jsonData = JSON.parse(content);

        // 处理distPath格式，与loadData中保持一致
        if (jsonData.distPath && typeof jsonData.distPath === 'string') {
          jsonData.distPath = [
            {
              uid: 'imported',
              name: '导入的文件',
              status: 'done',
              url: OSS_HOST + jsonData.distPath,
              response: jsonData.distPath,
            } as UploadFile,
          ];
        }

        // 设置旧数据并强制重新渲染表单
        setOldData(jsonData);
        // 更新key强制重新渲染
        setFormKey(Date.now());
        message.success('导入成功');
        setImportModalVisible(false);
        setImportFileList([]);
      } catch (error) {
        message.error('解析 JSON 文件失败');
        console.error(error);
      }
    };

    if (file.originFileObj) {
      reader.readAsText(file.originFileObj);
    } else {
      message.error('文件读取失败');
    }
  };

  return (
    <ProCard
      title={id ? '更新生成器' : '创建生成器'}
      extra={
        <Button type="primary" onClick={() => setImportModalVisible(true)}>
          一键导入元数据
        </Button>
      }
    >
      {/* 导入元数据弹窗 */}
      <Modal
        title="导入元数据"
        open={importModalVisible}
        onOk={handleImport}
        onCancel={() => {
          setImportModalVisible(false);
          setImportFileList([]);
        }}
        okText="导入"
        cancelText="取消"
        width={600}
        destroyOnClose
      >
        <Upload.Dragger
          name="file"
          fileList={importFileList}
          beforeUpload={beforeImportUpload}
          onChange={handleImportChange}
          accept=".json"
          maxCount={1}
          style={{ padding: '24px 16px', background: '#fafafa' }}
        >
          <p style={{ fontSize: 16, margin: '16px 0' }}>
            <CloudUploadOutlined style={{ fontSize: 48, color: '#1890ff' }} />
          </p>
          <p style={{ fontSize: 16, fontWeight: 500 }}>点击或拖拽 JSON 文件到此处上传</p>
          <p style={{ color: 'rgba(0,0,0,.45)' }}>支持单个文件导入，文件大小不超过 50MB</p>
        </Upload.Dragger>

        <div style={{ marginTop: 24 }}>
          <div style={{ marginBottom: 8 }}>
            <InfoCircleOutlined style={{ color: '#faad14', marginRight: 8 }} />
            <span style={{ color: 'rgba(0,0,0,.85)' }}>导入说明</span>
          </div>
          <div style={{ color: 'rgba(0,0,0,.65)', lineHeight: '22px' }}>
            <p>1. 请确保 JSON 文件符合生成器元数据格式规范</p>
            <p>2. 导入后将自动填充表单内容，您仍可手动调整数据</p>
            <p>3. 同名文件将会覆盖现有表单数据</p>
          </div>
        </div>
      </Modal>

      {/* 创建或者已加载要更新的数据时，才渲染表单，顺利填充默认值 */}
      {(!id || oldData) && (
        <StepsForm<API.GeneratorAddRequest>
          // 使用key强制重新渲染
          key={formKey}
          formRef={formRef}
          formProps={{
            initialValues: oldData,
          }}
          onFinish={doSubmit}
        >
          <StepsForm.StepForm<{
            name: string;
          }>
            name="base"
            title="基本信息"
            onFinish={async (values) => {
              setBasicInfo(values);
              return true;
            }}
          >
            <ProFormText
              name="name"
              label="名称"
              placeholder="请输入名称"
              rules={[
                {
                  required: true,
                  message: '请输入名称',
                },
                {
                  pattern: /^[a-zA-Z]+(?:[a-zA-Z_-]*[a-zA-Z]+)*$/,
                  message: '名称只能包含英文、下划线和中划线，且不能以下划线或中划线开头或结尾',
                },
              ]}
            />
            <ProFormText
              name="basePackage"
              label="基础包名"
              placeholder="请输入基础包名"
              rules={[
                {
                  required: true,
                  message: '请输入基础包名',
                },
                {
                  pattern: /^[a-zA-Z]+(?:\.[a-zA-Z]+)*$/,
                  message: '基础包名只能包含英文和点，且不能以点开头或结尾',
                },
              ]}
            />
            <ProFormTextArea
              name="description"
              label="描述"
              placeholder="请输入描述"
              rules={[{ required: true, message: '请输入描述' }]}
            />
            <ProFormText name="author" label="作者" placeholder="请输入作者" />
            <ProFormText
              name="version"
              label="版本号"
              placeholder="请输入版本号"
              rules={[
                {
                  required: true,
                  message: '请输入版本号',
                },
                {
                  pattern: /^[0-9]+(?:\.[0-9]+)*$/,
                  message: '名称只能包含数字和小数点，且不能以小数点开头或结尾',
                },
              ]}
            />
            <ProFormSelect name="tags" label="标签" mode="tags" placeholder="请输入标签" />
            <ProFormItem label="图片" name="picture">
              <PictureUploader biz="generator_picture" />
            </ProFormItem>
          </StepsForm.StepForm>
          <StepsForm.StepForm
            name="modelConfig"
            title="模型配置"
            onFinish={async (values) => {
              setModelConfig(values);
              return true;
            }}
          >
            <ModelConfigForm formRef={formRef} oldData={oldData} />
          </StepsForm.StepForm>
          <StepsForm.StepForm
            name="fileConfig"
            title="文件配置"
            onFinish={async (values) => {
              setFileConfig(values);
              return true;
            }}
          >
            <FileConfigForm formRef={formRef} oldData={oldData} />
          </StepsForm.StepForm>
          <StepsForm.StepForm name="dist" title="生成器文件">
            <ProFormItem label="产物包" name="distPath">
              <FileUploader
                biz="generator_dist"
                description="请上传生成器文件压缩包"
                accept=".zip,.rar,.7z,.gz,.tar"
              />
            </ProFormItem>
            <GeneratorMaker
              meta={{
                ...basicInfo,
                ...modelConfig,
                ...fileConfig,
              }}
            />
          </StepsForm.StepForm>
        </StepsForm>
      )}
    </ProCard>
  );
};

export default GeneratorAddPage;
